package com.zsk.shop.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.service.schema.util.StringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zsk.shop.common.base.model.token.TokenInfoModel;
import com.zsk.shop.common.base.model.token.UserSimple;
import com.zsk.shop.common.constant.Constant;
import com.zsk.shop.common.constant.RedisKeys;
import com.zsk.shop.entity.DataDictionary;
import com.zsk.shop.entity.TokenInfo;
import com.zsk.shop.enums.ServiceKeyTypeEnum;
import com.zsk.shop.service.DataDictionaryService;
import com.zsk.shop.service.TokenInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author yuwenbo
 * @description:
 * @date 2019-05-24 22:32
 */
@Component
public class TokenUtil {

    private final static Logger logger = LoggerFactory.getLogger(TokenUtil.class);

    public static final Integer tokenExpireDay = 10;// 默认10天，根据数据字典走
    public static final Long tokenExpireTime = 10 * 60L * 60L * 24L;// 10天

    @Autowired
    private TokenInfoService tokenInfoService;

    @Autowired
    private DataDictionaryService dictionaryService;

    public static TokenInfoModel getToken() {
        ServletRequestAttributes request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
        if (request == null) {
            return null;
        }
        String auth = "";
        if (request.getRequest().getRequestURI().contains("/h5")) {
            Map<String, String[]> map = request.getRequest().getParameterMap();
            auth = JSON.toJSONString(map.get("token"));
            auth = auth.substring(2, auth.length() - 2);
        } else {
            auth = request.getRequest().getHeader("Authorization");
        }
        if (StringUtil.isEmpty(auth)) {
            logger.info("Header获取Authorization为空");
            return null;
        }
        TokenInfoModel tokenInfoModel = null;
        try {
            tokenInfoModel = verifyToken(auth);
        } catch (Exception e) {
            logger.info("token有误");
        }
        return tokenInfoModel;
    }

    //生成token ,失效时间为天
    public String genToken(UserSimple userSimple, String day) {
        //生成新的token
        String token = DateUtils.format(new Date(), DateUtils.YYYYMMDDHHMMSS1) + UUID.randomUUID().toString();
        String hashKey;
        userSimple.setIsGop(ToolUtil.isEmpty(userSimple.getIsGop()) ? false : userSimple.getIsGop());
        //最好再存放到数据库显示，好排查，且不删除数据
        if (userSimple.getIsGop()) {
            hashKey = RedisKeys.gopUser.getHashKey(token);
        } else {
            hashKey = RedisKeys.appUser.getHashKey(token);
        }
        if (ToolUtil.isNotEmpty(day)) {
            Integer dayInt = Integer.parseInt(day);
            userSimple.setInvalidDate(DateUtils.addDay(dayInt));
            RedisUtil.put(hashKey, token, JSONObject.toJSONString(userSimple));
            RedisUtil.expire(hashKey, dayInt * 60L * 60L * 24L, TimeUnit.SECONDS);
        } else {
            userSimple.setInvalidDate(DateUtils.addDay(getTokenExpireDay()));
            RedisUtil.put(hashKey, token, JSONObject.toJSONString(userSimple));
            RedisUtil.expire(hashKey, getTokenExpireTime(), TimeUnit.SECONDS);
        }
        //token叠加到数据库
        TokenInfo tokenInfo = TokenInfo.builder()
                .tokenNo(RedisUtil.getServiceKeyHaveDateByType(ServiceKeyTypeEnum.TOKEN.getValue())).token(token).userId(userSimple.getId()).isGop(userSimple.getIsGop()).invalid(false).invalidDate(userSimple.getInvalidDate())
                .createTime(new Date()).updateTime(new Date()).build();
        //只做记录
        tokenInfoService.save(tokenInfo);
        return token;
    }

    private Long getTokenExpireTime() {
        DataDictionary dataDictionary = dictionaryService.getValueByKey(Constant.TOKEN_INVALID_DAY_KEY);
        if (ToolUtil.isEmpty(dataDictionary)) {
            return tokenExpireTime;
        } else {
            try {
                return Integer.parseInt(dataDictionary.getValue()) * 60L * 60L * 24L;
            } catch (Exception e) {
                return tokenExpireTime;
            }
        }
    }

    private Integer getTokenExpireDay() {
        LambdaQueryWrapper<DataDictionary> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DataDictionary::getKey, Constant.TOKEN_INVALID_DAY_KEY);
        queryWrapper.last("limit 1");
        DataDictionary dataDictionary = dictionaryService.getOne(queryWrapper);
        if (ToolUtil.isEmpty(dataDictionary)) {
            return tokenExpireDay;
        } else {
            try {
                return Integer.parseInt(dataDictionary.getValue());
            } catch (Exception e) {
                return tokenExpireDay;
            }
        }
    }

    //校验token
    public static TokenInfoModel verifyToken(String token) {
        TokenInfoModel tokenInfoModel;
        Object obj = RedisUtil.getHashKey(RedisKeys.appUser.getHashKey(token), token);
        if (ToolUtil.isEmpty(obj)) {
            obj = RedisUtil.getHashKey(RedisKeys.gopUser.getHashKey(token), token);
        }
        if (ToolUtil.isEmpty(obj)) {
            obj = RedisUtil.getHashKey(RedisKeys.touristUser.getHashKey(token), token);
        }
        tokenInfoModel = JSONObject.parseObject((String) obj, TokenInfoModel.class);
        return tokenInfoModel;
    }

}
